package match

import (
	"context"
	"github.com/stretchr/testify/assert"
	"gitverse.ru/synapse/kubelatte/pkg/api/common"
	"gitverse.ru/synapse/kubelatte/pkg/api/v1alpha1"
	"k8s.io/api/admission/v1beta1"
	"testing"
)

func Test_doesMatchExpressionsMatch(t *testing.T) {
	type args struct {
		searchData map[string]string
		matchExp   []v1alpha1.MatchExpression
	}
	tests := []struct {
		name string
		args args
		want bool
	}{
		{
			name: "In true",
			args: args{
				searchData: map[string]string{
					"name": "test",
				},
				matchExp: []v1alpha1.MatchExpression{
					{
						Key:      "name",
						Operator: "In",
						Values:   []string{"test"},
					},
				},
			},
			want: true,
		},
		{
			name: "In false",
			args: args{
				searchData: map[string]string{
					"name": "name",
				},
				matchExp: []v1alpha1.MatchExpression{
					{
						Key:      "name",
						Operator: "In",
						Values:   []string{"test"},
					},
				},
			},
			want: false,
		},
		{
			name: "NotIn true",
			args: args{
				searchData: map[string]string{
					"name": "name",
				},
				matchExp: []v1alpha1.MatchExpression{
					{
						Key:      "name",
						Operator: "NotIn",
						Values:   []string{"test"},
					},
				},
			},
			want: true,
		},
		{
			name: "NotIn false",
			args: args{
				searchData: map[string]string{
					"name": "test",
				},
				matchExp: []v1alpha1.MatchExpression{
					{
						Key:      "name",
						Operator: "NotIn",
						Values:   []string{"test"},
					},
				},
			},
			want: false,
		},
		{
			name: "Exists true",
			args: args{
				searchData: map[string]string{
					"name": "test",
				},
				matchExp: []v1alpha1.MatchExpression{
					{
						Key:      "name",
						Operator: "Exists",
					},
				},
			},
			want: true,
		},
		{
			name: "Exists false",
			args: args{
				searchData: map[string]string{
					"test": "name",
				},
				matchExp: []v1alpha1.MatchExpression{
					{
						Key:      "name",
						Operator: "Exists",
					},
				},
			},
			want: false,
		},
		{
			name: "DoesNotExist true",
			args: args{
				searchData: map[string]string{
					"test": "name",
				},
				matchExp: []v1alpha1.MatchExpression{
					{
						Key:      "name",
						Operator: "DoesNotExist",
					},
				},
			},
			want: true,
		},
		{
			name: "DoesNotExist false",
			args: args{
				searchData: map[string]string{
					"name": "test",
				},
				matchExp: []v1alpha1.MatchExpression{
					{
						Key:      "name",
						Operator: "DoesNotExist",
					},
				},
			},
			want: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equalf(t, tt.want, doesMatchExpressionsMatch(tt.args.searchData, tt.args.matchExp), "doesMatchExpressionsMatch(%v, %v)", tt.args.searchData, tt.args.matchExp)
		})
	}
}

func TestIsMustProcess(t *testing.T) {
	type args struct {
		data  common.ARFields
		match v1alpha1.Match
	}
	tests := []struct {
		name string
		args args
		want bool
	}{
		{
			name: "delete operation",
			args: args{
				data: common.ARFields{
					Operation: v1beta1.Delete,
				},
				match: v1alpha1.Match{},
			},
			want: false,
		},
		{
			name: "not delete operation",
			args: args{
				data: common.ARFields{
					Operation: v1beta1.Create,
				},
				match: v1alpha1.Match{},
			},
			want: true,
		},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			var got = IsMustProcess(context.Background(), test.args.data, test.args.match)
			if got != test.want {
				t.Errorf("IsMustProcess() got = %v, want %v", got, test.want)
			}
		})
	}
}

func Test_checkStringsMatchingWithSliceRegexp(t *testing.T) {
	type args struct {
		rule        []string
		comparedVal string
	}
	tests := []struct {
		name string
		args args
		want bool
	}{
		{
			name: "value",
			args: args{
				rule:        []string{"eetets", "test"},
				comparedVal: "test",
			},
			want: true,
		},
		{
			name: "star",
			args: args{
				rule:        []string{"*"},
				comparedVal: "test",
			},
			want: true,
		},
		{
			name: "regex wrong",
			args: args{
				rule:        []string{"a(b`"},
				comparedVal: "test",
			},
			want: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equalf(t, tt.want, checkStringsMatchingWithSliceRegexp(tt.args.rule, tt.args.comparedVal), "checkStringsMatchingWithSliceRegexp(%v, %v)", tt.args.rule, tt.args.comparedVal)
		})
	}
}
